Is it possible to have 2 languages with different syntax but the same semantics?
Sure. I think it may be hard to answer the question using production languages since you are unlikely to find two "real" languages with identical semantics or identical syntax.

Let's consider a simpler example to illustrate the concepts. Take JSON (which I suppose isn't a programming language, per se, but the idea carries over). Now, change it so that instead of separating key-value pairs with colons we use equals signs and instead of separating items with commas we use semi-colons. Now it looks like this:

{
  "name" = "Bob";
  "age" = 23;
  "titles" = [ "Mr."; "Dr."; "Sir" ]
}


This is clearly semantically the same as the following, syntactically different string:

{
  "name" : "Bob",
  "age" : 23,
  "titles" : [ "Mr.", "Dr.", "Sir" ]
}


A bit of a simple example, but it should illustrate the point.

As far as the other direction is concerned, that is also true. For example, consider the standard for loop found in many languages:

for (int i = 0; i &lt; 10; i++) {
  // do something...
}


This loop runs the initialization step once at the beginning, tests the condition before each iteration of the body, then runs the update step at the end of each iteration. But I could define a language with the same syntax but where the condition is evaluated at the end of the iteration and the update occurs at the beginning. The standard version is semantically the same as:

int i = 0;
while (i &lt; 10) {
  // do something
  i++;
}


whereas my new definition is equivalent to

int i = 0;
do {
  i++;
  // do something
} while (i &lt; 10);


which is clearly different.